//Nic Lupfer

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include "query.h"

using namespace std;

	Query::Query(){
		numQuery = 1;
	}

	Query::Query(Table* t){
		table = t;
		numQuery = 1;
	}


	string Query::doQuery(string from, string wher, string select){
		vector<Table*> t = From(from);
		//cout<<"FROM Table Size: "<< t.size()<<endl;
		vector<Record*> r = Where(wher, t);
		Table*view = Select(select, r, t);
		Table*tmp=table->next;
		table->next=view;
		view->next=tmp;
		return view->TableName;

	}

//THIS FUNCTION TAKES A STRING AND REMOVES SURROUNDING SPACES AND RETURN THE STRING.
string Query::RemoveSpace(string tstring){
	string temp;
	stringstream stream;
	stream.str(tstring);
	char c, t;
	int flag=0;
	stream.get(c);
	while(isspace(c))
		stream.get(c);
	temp.clear();
	while(!stream.eof()){
		if(!isspace(c))
			flag=1;
		if(c==' '){
			t=c;
			stream.get(c);
			if(!isspace(c) && (flag==1)){
				temp+=t;
			}
			else
				flag=0;
		}
		if(flag == 1){
			temp+=c;
			stream.get(c);
		}
		else
			stream.get(c);
	}
	return temp;
}



	vector<Record*> Query::find(string from, string wher){
		vector<Table*> t = From(from);
		vector<Record*> r = Where(wher, t);
		return r;
	}


	vector<Table*> Query::From(string from){
		
		//cout << "From: "<<from<<endl;
		vector <string > tableNames;
		string  temp;

		while (from.find(",", 0) != string::npos)
		{ 
			size_t  pos = from.find(",", 0); //store the position of the delimiter
			temp = from.substr(0, pos);      //get the token
			from.erase(0, pos + 1);          //erase it from the source 
			tableNames.push_back(RemoveSpace(temp));                //and put it into the array
		}

		tableNames.push_back(RemoveSpace(from));           //the last token is all alone 
		


		vector<Table*> tables;		
		
		Table* t = table;
		for(int i=0;i<int(tableNames.size());i++)
			//cout << tableNames[i] <<endl;
		
		while(t->next != NULL){
			for(int i = 0; i < (int)(tableNames.size()); i++){
				//cout << "Checking: "<<t->next->TableName<<" = "<< tableNames[i]<<endl;
				if(t->next->TableName == tableNames[i]){
					tables.push_back(t->next);
					//cout << "Found Table: "<<t->next->TableName<<endl;
				}
			}
			t = t->next;
		}
		if(tables.size() == 0)
			cout << "ERROR: No tables found.";
		
		//cout<<"Table Names :"<<endl;
		for(int i = 0; i < (int)(tableNames.size()); i++){
			//cout<<tableNames[i]<<endl;			
		}

		//cout<<"Tables :"<<endl;
		for(int i = 0; i < (int)(tables.size()); i++){
			//cout<<tables[i]->TableName<<endl;			
		}

		return tables;
	}


	QTokenType Query::isTokenType(string s){
		if(s == "(")
			return tkOpenPar;
		else if(s == ")")
			return tkClosePar;
		else if(s == "AND")
			return tkAnd;
		else if(s == "OR")
			return tkOr;
		else if(s == "NOT")
			return tkNot;
		else if(s == "IN")
			return tkIn;
		else if(s == "EXISTS")
			return tkExists;
		else if(s == "=")
			return tkEquals;
		else if(s == "!=")
			return tkNotEquals;
		else if(s == "<")
			return tkLessThan;
		else if(s == "<=")
			return tkLessThanEq;
		else if(s == ">")
			return tkGreatThan;
		else if(s == ">=")
			return tkGreatThanEq;
		else if(s == "ALL")
			return tkAll;
		else if(s == "ANY")
			return tkAny;
		else if(s == "*")
			return tkStar;
		else if(s == "AS")
			return tkAs;
		else if(s == "SUM")
			return tkSum;
		else if(s == "MAX")
			return tkMax;
		else if(s == "MIN")
			return tkMin;
		else if(s == "COUNT")
			return tkCount;

		return tkValue;
	}

	//Every thing in the statement needs to be separated with a space
	//Example: ( ( A = B ) AND ( A = C ) ) OR A = D
	//WRONG Example: ((A=B) AND ( A=C))OR A=D
	vector<Record*> Query::Where(string wher, vector<Table*> tables){
		
		vector<Record*> validRecords;

		if(tables.size() != 0){

			//cout << "Where: "<<wher<<endl;
			vector<Token> tokens;
			wher+=' ';
			string t;
			stringstream s;
			s << wher;
			s >> t;
			do{
				QTokenType type = isTokenType(t);
				Token token;
				token.type = type;
				if(type == tkValue)
					token.value = t;

				tokens.push_back(token);
				//cout << "Token: "<<token.type<<endl;
				s >> t;	
			}while(!s.eof());
			
			vector<Token> operations;
			bool wrong = false;

			for(int i = 0; i < (int)(tokens.size()); i++){
				if(tokens[i].type == tkEquals || tokens[i].type == tkNotEquals ||
				   tokens[i].type == tkLessThan || tokens[i].type == tkLessThanEq ||
				   tokens[i].type == tkGreatThan || tokens[i].type == tkGreatThanEq){
					
					string value1 = "";
					int n = 1;
					while(i-n >= 0){
						if(tokens[i-n].type == tkValue){
							if(value1 == "")
								value1 = tokens[i-n].value;
							else
								value1 = tokens[i-n].value + " "+value1;
						}
						else
							n = 10000;

						n++;
					}
					if(value1 == "")
						wrong = true;
					
					string value2 = "";
					if(i+1 < (int)(tokens.size())){
						if(tokens[i+1].type == tkAll){
							n = 2;
							while(i+n < (int)(tokens.size())){
								if(tokens[i+n].type == tkValue){
									if(value2 == "")
										value2 = tokens[i+n].value;
									else
										value2 = value2 + " " + tokens[i+n].value;
								}
								else
									n = (int)(tokens.size());

								n++;
							}
							Token t;
							t.type = tkExp;
							t.records = allExp(value1, tokens[i].type, value2, tables);
							operations.push_back(t);
						}
						else if(tokens[i+1].type == tkAny){
							n = 2;
							while(i+n < (int)(tokens.size())){
								if(tokens[i+n].type == tkValue){
									if(value2 == "")
										value2 = tokens[i+n].value;
									else
										value2 = value2 + " " + tokens[i+n].value;
								}
								else
									n = (int)(tokens.size());

								n++;
							}
							Token t;
							t.type = tkExp;
							t.records = anyExp(value1, tokens[i].type, value2, tables);
							operations.push_back(t);
						}
						else if(tokens[i+1].type == tkValue){
							n = 1;
							while(i+n < (int)(tokens.size())){
								if(tokens[i+n].type == tkValue){
									if(value2 == "")
										value2 = tokens[i+n].value;
									else
										value2 = value2 + " " + tokens[i+n].value;
								}
								else
									n = (int)(tokens.size());

								n++;
							}
							Token t;
							t.type = tkExp;
							t.records = expression(value1, tokens[i].type, value2, tables);
							operations.push_back(t);
						}
					}
					if(value2 == "")
						wrong = true;
				}
				else if(tokens[i].type == tkIn){
					string value1 = "";
					int n = 1;
					while(i-n >= 0){
						if(tokens[i-n].type == tkValue){
							if(value1 == "")
								value1 = tokens[i-n].value;
							else
								value1 = value1 + " " + tokens[i-n].value;
						}
						else
							n = 10000;

						n++;
					}
					if(value1 == "")
						wrong = true;

					string value2 = "";
					n = 1;
					while(i+n < (int)(tokens.size())){
						if(tokens[i+n].type == tkValue){
							if(value2 == "")
								value2 = tokens[i+n].value;
							else
								value2 = value2 + " " + tokens[i+n].value;
						}
						else
							n = 10000;

						n++;
					}
					if(value2 == "")
						wrong = true;

					Token t;
					t.type = tkExp;
					t.records = inExp(value1, value2, tables);
					operations.push_back(t);
					
				}
				else if(tokens[i].type == tkExists){
					string value1 = "";
					int n = 1;
					while(i+n < (int)(tokens.size())){
						if(tokens[i+n].type == tkValue){
							if(value1 == "")
								value1 = tokens[i+n].value;
							else
								value1 = value1 + " " + tokens[i+n].value;
						}
						else
							n = 10000;

						n++;
					}
					if(value1 == "")
						wrong = true;

					Token t;
					t.type = tkExp;
					t.records = existsExp(value1, tables);
					operations.push_back(t);				
				}
				else if(tokens[i].type == tkAnd || tokens[i].type == tkOr ||
						tokens[i].type == tkNot ||tokens[i].type == tkOpenPar || tokens[i].type == tkClosePar){
					operations.push_back(tokens[i]);
				}
			}			

			if(wrong){
				cout << "Wrong input in WHERE statement.";
				return validRecords;
			}
			else{		
				bool done = false;
				while(!done){
					vector<Token> evaluated;
					for(int i = 0; i < (int)(operations.size()); i++){
						if(operations[i].type == tkExp && i-1 >= 0  && i+1 < (int)(operations.size())){
							if(operations[i-1].type == tkOpenPar && operations[i+1].type == tkClosePar){
								evaluated.push_back(operations[i]);
								//cout<<"Evaluted'd"<<endl;
								i+=2;
							}
						}
						else if(operations[i].type == tkAnd && i-1 >= 0  && i+1 < (int)(operations.size())){
							if(operations[i-1].type == tkExp && operations[i+1].type == tkExp){
								Token t;
								t.type = tkExp;
								t.records = and(operations[i-1].records, operations[i+1].records);							
								evaluated.push_back(t);
								i+=2;
								//cout<<"AND'd"<<endl;
							}
						}
						else if(operations[i].type == tkOr && i-1 >= 0  && i+1 < (int)(operations.size())){
							if(operations[i-1].type == tkExp && operations[i+1].type == tkExp){
								Token t;
								t.type = tkExp;
								t.records = or(operations[i-1].records, operations[i+1].records);							
								evaluated.push_back(t);
								i+=2;
								//cout<<"OR'd"<<endl;
							}
						}
						else if(operations[i].type == tkNot && i+1 < (int)(operations.size())){
							if(operations[i+1].type == tkExp){
								Token t;
								t.type = tkExp;
								t.records = not(operations[i+1].records, tables);							
								evaluated.push_back(t);
								i+=2;
								//cout<<"NOT'd"<<endl;
							}
						}
						else if(operations[i].type == tkAnd || operations[i].type == tkOr && i+1 >= (int)(operations.size())){
							evaluated.push_back(operations[i]);
							evaluated.push_back(operations[i+1]);
						}
						else if(operations[i].type == tkAnd || operations[i].type == tkOr && i-1 >= 0){
							evaluated.push_back(operations[i-1]);
							evaluated.push_back(operations[i]);
						}						
						else if(operations[i].type == tkOpenPar || operations[i].type == tkClosePar){
							evaluated.push_back(operations[i]);
						}

					}
					if(operations.size() == 1)
						evaluated.push_back(operations[0]);

					//cout<<"Evaluation :"<<endl;
					for(int i = 0; i < (int)(evaluated.size()); i++){
						//cout<<evaluated[i].type<<endl;						
					}
					if(evaluated.size() == 1){
						validRecords = evaluated[0].records;
						done = true;
					}
					operations = evaluated;
				}
			}
			//cout<<"Records :"<<endl;
			for(int i = 0; i < (int)(validRecords.size()); i++){
				Record* r = validRecords[i];
				void* recordAtrb = r->next->RecordPtr[0];
				string s = *((string*)recordAtrb);
				//cout<<s<<endl;
				
			}
		}
		return validRecords;		
	}	
	vector<Record*> Query::expression(string attribute, QTokenType tk, string value, vector<Table*> tables){
		//cout<< "Evaluating Expression "<< attribute<<" "<<tk<<" "<<value<<" Tables Size: "<< tables.size()<<endl;
		vector<Record*> validRecords;
		Table* fromTable=NULL;
		FieldType type = InvalidType;
		int attributeIndex = -1;
		for(int i = 0; i < (int)(tables.size()); i++){
			for(int j = 0; j < (int)(tables[i]->AttributeName.size()); j++){
				//cout<<"Testing: "<<tables[i]->AttributeName[j]<<" == "<<attribute<<endl;
				if(tables[i]->AttributeName[j] == attribute){
					attributeIndex = j;
					type = tables[i]->AttributeType[j];
					fromTable = tables[i];
				}
			}
		}
		//cout<< "From Table: "<< fromTable->TableName<<endl;
		if(fromTable != NULL){
			Record* r = fromTable->StartRec;
			while(r->next != NULL){
				void* recordAtrb = r->next->RecordPtr[attributeIndex];
				float valueFloat = (float)atof(value.c_str());
				int valueInt = (int)atof(value.c_str()); 
				
				if(type == StringType)
				{
					if(tk == tkEquals){
						string s = *((string*)recordAtrb);
						if(s == value)
							validRecords.push_back(r);
					}
					else if(tk == tkNotEquals){
						string s = *((string*)recordAtrb);
						if(s != value)
							validRecords.push_back(r);
					}				
				}
				else if(type == FloatType)
				{
					if(tk == tkEquals){
						float s = *((float*)recordAtrb);
						if(s == (float)(valueFloat))
							validRecords.push_back(r);
					}
					else if(tk == tkNotEquals){
						float s = *((float*)recordAtrb);
						if(s != (float)(valueFloat))
							validRecords.push_back(r);
					}
					else if(tk == tkLessThan){
						float s = *((float*)recordAtrb);
						if(s < (float)(valueFloat))
							validRecords.push_back(r);
					}
					else if(tk == tkLessThanEq){
						float s = *((float*)recordAtrb);
						if(s <= (float)(valueFloat))
							validRecords.push_back(r);
					}
					else if(tk == tkGreatThan){
						float s = *((float*)recordAtrb);
						if(s > (float)(valueFloat))
							validRecords.push_back(r);
					}
					else if(tk == tkGreatThanEq){
						float s = *((float*)recordAtrb);
						if(s >= (float)(valueFloat))
							validRecords.push_back(r);
					}
				}
				else if(type == IntType)
				{
					if(tk == tkEquals){
						int s = *((int*)recordAtrb);
						if(s == (int)(valueInt))
							validRecords.push_back(r);
					}
					else if(tk == tkNotEquals){
						int s = *((int*)recordAtrb);
						if(s != (int)(valueInt))
							validRecords.push_back(r);
					}
					else if(tk == tkLessThan){
						int s = *((int*)recordAtrb);
						if(s < (int)(valueInt))
							validRecords.push_back(r);
					}
					else if(tk == tkLessThanEq){
						int s = *((int*)recordAtrb);
						if(s <= (int)(valueInt))
							validRecords.push_back(r);
					}
					else if(tk == tkGreatThan){
						int s = *((int*)recordAtrb);
						if(s > (int)(valueInt))
							validRecords.push_back(r);
					}
					else if(tk == tkGreatThanEq){
						int s = *((int*)recordAtrb);
						if(s >= (int)(valueInt))
							validRecords.push_back(r);
					}
				}
				r=r->next;
			}
		}
		//cout<<"Records :"<<endl;
		for(int i = 0; i < (int)(validRecords.size()); i++){
			Record* r = validRecords[i];
			void* recordAtrb = r->next->RecordPtr[0];
			string s = *((string*)recordAtrb);
			//cout<<s<<endl;
			
		}
		return validRecords;
	}	
	vector<Record*> Query::inExp(string attribute, string value, vector<Table*> tables){
		//cout<<"In Statment "<<attribute<<" "<<value<<endl;
		
		vector<Record*> validRecords;
		Table* fromTable = NULL;
		int attributeIndex = -1;
		for(int i = 0; i < (int)(tables.size()); i++){
			for(int j = 0; j < (int)(tables[i]->AttributeName.size()); j++){
				if(tables[i]->AttributeName[j] == attribute){
					attributeIndex = j;
					fromTable = tables[i];
					//cout<<"Found fromTable: "<< fromTable->TableName<<endl;
				}
			}
		}
		Table* valueTable = NULL;
		Table* t = Query::table;
		while(t->next != NULL){
			if(t->next->TableName ==  value){
				valueTable = t->next;
			}
			t = t->next;
		}
		if(fromTable != NULL && valueTable != NULL){
			Record* r = fromTable->StartRec;
			while(r->next != NULL){
				void* recordAtrb = r->next->RecordPtr[attributeIndex];
				string v = *((string*)recordAtrb);			
				Record* rIn = valueTable->StartRec;
				while(rIn->next != NULL){
					void* rInAtrb = rIn->next->RecordPtr[0];
					string tempV = *((string*)rInAtrb);
					if(tempV == v)
						validRecords.push_back(r);
					rIn = rIn->next;
				}
				r = r->next;
			}
		}
		//cout<<"Records :"<<endl;
		for(int i = 0; i < (int)(validRecords.size()); i++){
			Record* r = validRecords[i];
			void* recordAtrb = r->next->RecordPtr[0];
			string s = *((string*)recordAtrb);
			//cout<<s<<endl;			
		}
		return validRecords;
	}

	vector<Record*> Query::existsExp(string value, vector<Table*> tables){
		
		vector<Record*> validRecords;
		
		Table* valueTable;
		Table* t = table;
		while(t->next != NULL){
			if(t->next->TableName ==  value){
				valueTable = t->next;
			}
			t = t->next;
		}

		if(valueTable->StartRec->next != NULL){
			for(int i = 0; i < (int)(tables.size()); i++){
				Record* r = tables[i]->StartRec;
				while(r->next != NULL){
					validRecords.push_back(r);
					r = r->next;
				}
			}
		}
		//cout<<"Records :"<<endl;
		for(int i = 0; i < (int)(validRecords.size()); i++){
			Record* r = validRecords[i];
			void* recordAtrb = r->next->RecordPtr[0];
			string s = *((string*)recordAtrb);
			//cout<<s<<endl;			
		}
		return validRecords;
	}

	vector<Record*> Query::allExp(string attribute, QTokenType tk, string value, vector<Table*> tables){
		vector<Record*> validRecords;
		Table* fromTable = NULL;
		FieldType type = InvalidType;
		int attributeIndex = -1;
		for(int i = 0; i < (int)(tables.size()); i++){
			for(int j = 0; j < (int)(tables[i]->AttributeName.size()); j++){
				if(tables[i]->AttributeName[j] == attribute){
					attributeIndex = j;
					fromTable = tables[i];
					type = tables[i]->AttributeType[j];
				}
			}
		}

		Table* valueTable = NULL;
		Table* t = table;
		while(t->next != NULL){
			if(t->next->TableName ==  value){
				valueTable = t->next;
			}
			t = t->next;
		}
	
		if(fromTable != NULL && valueTable != NULL){
			Record* r = fromTable->StartRec;
			while(r->next != NULL){
				void* recordAtrb = r->next->RecordPtr[attributeIndex];				
				Record* valueRec = valueTable->StartRec;
				bool goodForAll = true;
				while(valueRec->next != NULL){
					void* valPtr = valueRec->next->RecordPtr[0];					
					if(type == StringType)
					{
						if(tk == tkEquals){
							string s = *((string*)recordAtrb);
							string v = *((string*)valPtr);
							if(s != v)
								goodForAll = false;
						}
						else if(tk == tkNotEquals){
							string s = *((string*)recordAtrb);
							string v = *((string*)valPtr);
							if(s == v)
								goodForAll = false;
						}				
					}
					else if(type == FloatType)
					{
						if(tk == tkEquals){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s != v)
								goodForAll = false;
						}
						else if(tk == tkNotEquals){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s == v)
								goodForAll = false;
						}
						else if(tk == tkLessThan){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s >= v)
								goodForAll = false;
						}
						else if(tk == tkLessThanEq){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s > v)
								goodForAll = false;
						}
						else if(tk == tkGreatThan){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s <= v)
								goodForAll = false;
						}
						else if(tk == tkGreatThanEq){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s < v)
								goodForAll = false;
						}
					}
					else if(type == IntType)
					{
						if(tk == tkEquals){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s != v)
								goodForAll = false;
						}
						else if(tk == tkNotEquals){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s == v)
								goodForAll = false;
						}
						else if(tk == tkLessThan){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s >= v)
								goodForAll = false;
						}
						else if(tk == tkLessThanEq){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s > v)
								goodForAll = false;
						}
						else if(tk == tkGreatThan){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s <= v)
								goodForAll = false;
						}
						else if(tk == tkGreatThanEq){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s < v)
								goodForAll = false;
						}
					}
					valueRec = valueRec->next;										
				}
				if(goodForAll)
					validRecords.push_back(r);

				r=r->next;
			}
		}
		//cout<<"Records :"<<endl;
		for(int i = 0; i < (int)(validRecords.size()); i++){
			Record* r = validRecords[i];
			void* recordAtrb = r->next->RecordPtr[0];
			string s = *((string*)recordAtrb);
			//cout<<s<<endl;
			
		}
		return validRecords;
	}

	vector<Record*> Query::anyExp(string attribute, QTokenType tk, string value, vector<Table*> tables){
		vector<Record*> validRecords;
		Table* fromTable = NULL;
		FieldType type = InvalidType;
		int attributeIndex = -1;
		for(int i = 0; i < (int)(tables.size()); i++){
			for(int j = 0; j < (int)(tables[i]->AttributeName.size()); j++){
				if(tables[i]->AttributeName[j] == attribute){
					attributeIndex = j;
					type = tables[i]->AttributeType[j];
					fromTable = tables[i];
				}
			}
		}

		Table* valueTable = NULL;
		Table* t = table;
		while(t->next != NULL){
			if(t->next->TableName ==  value){
				valueTable = t->next;
			}
			t = t->next;
		}
		
		if(fromTable != NULL && valueTable != NULL){

			Record* r = fromTable->StartRec;
			while(r->next != NULL){
				void* recordAtrb = r->next->RecordPtr[attributeIndex];				
				Record* valueRec = valueTable->StartRec;
				bool goodForOne = false;
				while(valueRec->next != NULL){
					void* valPtr = valueRec->next->RecordPtr[0];
					
					if(type == StringType)
					{
						if(tk == tkEquals){
							string s = *((string*)recordAtrb);
							string v = *((string*)valPtr);
							if(s == v)
								goodForOne = true;
						}
						else if(tk == tkNotEquals){
							string s = *((string*)recordAtrb);
							string v = *((string*)valPtr);
							if(s != v)
								goodForOne = true;
						}				
					}
					else if(type == FloatType)
					{
						if(tk == tkEquals){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s == v)
								goodForOne = true;
						}
						else if(tk == tkNotEquals){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s != v)
								goodForOne = true;
						}
						else if(tk == tkLessThan){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s < v)
								goodForOne = true;
						}
						else if(tk == tkLessThanEq){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s <= v)
								goodForOne = true;
						}
						else if(tk == tkGreatThan){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s > v)
								goodForOne = true;
						}
						else if(tk == tkGreatThanEq){
							float s = *((float*)recordAtrb);
							float v = *((float*)valPtr);
							if(s >= v)
								goodForOne = true;
						}
					}
					else if(type == IntType)
					{
						if(tk == tkEquals){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s == v)
								goodForOne = true;
						}
						else if(tk == tkNotEquals){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s != v)
								goodForOne = true;
						}
						else if(tk == tkLessThan){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s < v)
								goodForOne = true;
						}
						else if(tk == tkLessThanEq){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s <= v)
								goodForOne = true;
						}
						else if(tk == tkGreatThan){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s > v)
								goodForOne = true;
						}
						else if(tk == tkGreatThanEq){
							int s = *((int*)recordAtrb);
							int v = *((int*)valPtr);
							if(s >= v)
								goodForOne = true;
						}
					}
					valueRec = valueRec->next;
				}
				if(goodForOne)
						validRecords.push_back(r);				
				r=r->next;
			}
		}
		//cout<<"Records :"<<endl;
		for(int i = 0; i < (int)(validRecords.size()); i++){
			Record* r = validRecords[i];
			void* recordAtrb = r->next->RecordPtr[0];
			string s = *((string*)recordAtrb);
			//cout<<s<<endl;
			
		}
		return validRecords;
	}

	vector<Record*> Query::and(vector<Record*> a, vector<Record*> b){
		vector<Record*> validRecords;		
		for(int i = 0; i < (int)(a.size()); i++){
			bool isIn = false;
			for(int j = 0; j < (int)(b.size()); j++){
				if(a[i]==b[j]){
					j = (int)(b.size()) + 1;
					isIn = true;
				}
			}
			if(isIn)
				validRecords.push_back(a[i]);
		}
		return validRecords;
	}

	vector<Record*> Query::or(vector<Record*> a, vector<Record*> b){
		vector<Record*> validRecords = a;		
		for(int i = 0; i < (int)(b.size()); i++){
			bool isIn = false;
			for(int j = 0; j < (int)(a.size()); j++){
				if(b[i]==a[j]){
					j = (int)(a.size()) + 1;
					isIn = true;
				}
			}
			if(!isIn)
				validRecords.push_back(b[i]);
		}
		return validRecords;
	}
	vector<Record*> Query::not(vector<Record*> a, vector<Table*> tables){
		vector<Record*> validRecords;
		vector<Record*> allRecords;	
		for(int i = 0; i < (int)(tables.size()); i++){
			Record* r = tables[i]->StartRec;
			while(r->next != NULL){
				allRecords.push_back(r);	
				r = r->next;
			}
		}		
		for(int i = 0; i < (int)(allRecords.size()); i++){
			bool isIn = false;
			for(int j = 0; j < (int)(a.size()); j++){
				if(allRecords[i]==a[j]){
					j = (int)(a.size()) + 1;
					isIn = true;
				}
			}
			if(!isIn)
				validRecords.push_back(allRecords[i]);
		}
		return validRecords;
	}

	//Deep copy the data in Record from at column and push it into already initialized record to
	void Query::deepCopyRecord(Table*t,Record*to,Record*from,int column){
		string*stoInsert;
		float*ftoInsert;
		int*itoInsert;						//COPY the data
		switch(t->AttributeType[column]){
			case StringType:
				stoInsert=new string;
				(*stoInsert)=*(string*)(from->RecordPtr[column]);
				to->RecordPtr.push_back((void*)stoInsert);
				break;
			case FloatType:
				ftoInsert=new float;
				(*ftoInsert)=*(float*)(from->RecordPtr[column]);
				to->RecordPtr.push_back((void*)ftoInsert);
				break;
			case IntType:
				itoInsert=new int;
				(*itoInsert)=*(int*)(from->RecordPtr[column]);
				to->RecordPtr.push_back((void*)itoInsert);
				break;
		}
	}
	
	//SELECT Attribute Name, Attribute Name
	//SELECT *
	//SELECT *, COUNT, MIN Attribute Name, MAX Attribute Name, SUM Attribute Name
	//			MIN, MAX, and SUM Attributes must be of type int or float
	// * must be the first case 


	Table* Query::Select(string select, vector<Record*> records, vector<Table*> tables){
		cout<<"Select:"<<endl;
		
		Table* view = new Table;
		view->TableName = "Query Results";// " + numQuery;
		numQuery++;
		//cout<<"Making a Table Named: "<<view->TableName<<endl;
		if(tables.size() != 0){
			Record* r = view->StartRec;
			for(int i = 0; i < (int)(records.size()); i++){
				r->next = new Record;
				r->next->next=NULL;
				r = r->next;
			}
		
			vector<string> s;
			string  temp;

			while (select.find(",", 0) != string::npos)
			{ 
				size_t  pos = select.find(",", 0); //store the position of the delimiter
				temp = select.substr(0, pos);      //get the token
				select.erase(0, pos + 1);          //erase it from the source 
				s.push_back(RemoveSpace(temp));                //and put it into the array
			}

			s.push_back(RemoveSpace(select));           //the last token is all alone
			
			vector<Token> tokens;

			for(int i = 0; i < (int)(s.size()); i++){
				QTokenType type = isTokenType(s[i]);
				Token token;
				token.type = type;
				if(type == tkValue)
					token.value = s[i];

				tokens.push_back(token);
			}

			//for(int i=0;i<int(tokens.size());i++)
				//cout << tokens[i].type <<" "<<tokens[i].value <<endl;

			bool error = false;
			for(int i = 0; i < (int)(tokens.size()); i++){
				if(tokens[i].type == tkStar){
					//cout<<"Selecting All"<<endl;
					Table* fromTable = tables[0];
					for(int j = 0; j < (int)(fromTable->AttributeName.size()); j++){
						view->AttributeName.push_back(fromTable->AttributeName[j]);
						view->AttributeType.push_back(fromTable->AttributeType[j]);
						Record* r = view->StartRec;
						for(int k = 0; k < (int)(records.size()); k++){
							deepCopyRecord(fromTable,r->next,records[k]->next,j);
							r = r->next;
						}
					}
				}
				else if(tokens[i].type == tkAs && i-1 >= 0 && i+1 < (int)(tokens.size())){
					if(tokens[i-1].type == tkValue && tokens[i+1].type == tkValue){
						string newName = tokens[i+1].value;
						Table*fromTable = NULL;
						int attributeIndex = -1;
						for(int k = 0; k < (int)(tables.size()); k++){
							for(int j = 0; j < (int)(tables[k]->AttributeName.size()); j++){
								if(tables[k]->AttributeName[j] == tokens[i-1].value){
									attributeIndex = j;
									view->AttributeName.push_back(newName);
									view->AttributeType.push_back(tables[k]->AttributeType[j]);
									fromTable=tables[k];
								}
							}
						}
						if(fromTable != NULL){
							Record* r = view->StartRec;
							for(int j = 0; j < (int)(records.size()); j++){
								if(attributeIndex < (int)(records[j]->RecordPtr.size())){

									//r->next->RecordPtr.push_back(records[j]->RecordPtr[attributeIndex]);
									deepCopyRecord(fromTable,r->next,records[j]->next,attributeIndex);
									r = r->next;
								}
								else
									error = true;
							}
						}
						i++;
					}
					else
						error = true;
				}
				else if(tokens[i].type == tkCount){
					string tableNames = "";
					int count = 0;
					int* m = &count;
					for(int k = 0; k < (int)(tables.size()); k++){
						if(tableNames == "")
							tableNames = tables[k]->TableName;
						else
							tableNames += " "+tables[k]->TableName;

						Record* r = tables[k]->StartRec;
						while(r->next != NULL){
							count++;
						}
					}
					view->AttributeName.push_back("Count Of Records In "+tableNames);
					view->AttributeType.push_back(IntType);
					Record* r = view->StartRec;
					for(int j = 0; j < (int)(records.size()); j++){
						r->next->RecordPtr.push_back((void*)(m));
						r = r->next;
					}

				}
				else if(tokens[i].type == tkSum && i+1 < (int)(tokens.size())){
					if(tokens[i+1].type == tkValue){
						int attributeIndex = -1;
						Table* fromTable = NULL;
						for(int k = 0; k < (int)(tables.size()); k++){
							for(int j = 0; j < (int)(tables[k]->AttributeName.size()); j++){
								if(tables[k]->AttributeName[j] == tokens[i+1].value){
									attributeIndex = j;
									view->AttributeName.push_back("SUM Of "+(tables[k]->AttributeName[j]));
									view->AttributeType.push_back(FloatType);
									fromTable = tables[k];
								}
							}
						}
						if(fromTable != NULL){
							float sum = 0;
							float* m = &sum;
							Record* r = fromTable->StartRec;
							while(r->next != NULL){
								void* recordAtrb = r->next->RecordPtr[attributeIndex];
								float s = *((float*)recordAtrb);
								sum += s;

							}
							r = view->StartRec;
							for(int j = 0; j < (int)(records.size()); j++){
								r->next->RecordPtr.push_back((void*)(m));
								r = r->next;
							}
						}
						i++;
					}
					else
						error = true;
				}
				else if(tokens[i].type == tkMax && i+1 < (int)(tokens.size())){
					if(tokens[i+1].type == tkValue){
						int attributeIndex = -1;
						Table* fromTable = NULL;
						for(int k = 0; k < (int)(tables.size()); k++){
							for(int j = 0; j < (int)(tables[k]->AttributeName.size()); j++){
								if(tables[k]->AttributeName[j] == tokens[i+1].value){
									attributeIndex = j;
									view->AttributeName.push_back("MAX Of "+(tables[k]->AttributeName[j]));
									view->AttributeType.push_back(FloatType);
									fromTable = tables[k];
								}
							}
						}
						if(fromTable != NULL){
							float max = -10000000000;
							float* m = &max;
							Record* r = fromTable->StartRec;
							while(r->next != NULL){
								void* recordAtrb = r->next->RecordPtr[attributeIndex];
								float s = *((float*)recordAtrb);
								if(s > max)
									max = s;

							}
							r = view->StartRec;
							for(int j = 0; j < (int)(records.size()); j++){
								r->next->RecordPtr.push_back((void*)(m));
								r = r->next;
							}
						}
						i++;
					}
					else
						error = true;
				}
				else if(tokens[i].type == tkMin && i+1 < (int)(tokens.size())){
					if(tokens[i+1].type == tkValue){
						int attributeIndex = -1;
						Table* fromTable = NULL;
						for(int k = 0; k < (int)(tables.size()); k++){
							for(int j = 0; j < (int)(tables[k]->AttributeName.size()); j++){
								if(tables[k]->AttributeName[j] == tokens[i+1].value){
									attributeIndex = j;
									view->AttributeName.push_back("MIN Of "+(tables[k]->AttributeName[j]));
									view->AttributeType.push_back(FloatType);
									fromTable = tables[k];
								}
							}
						}
						if(fromTable != NULL){
							float min = 10000000000;
							float* m = &min;
							Record* r = fromTable->StartRec;
							while(r->next != NULL){
								void* recordAtrb = r->next->RecordPtr[attributeIndex];
								float s = *((float*)recordAtrb);
								if(s < min)
									min = s;

							}
							r = view->StartRec;
							for(int j = 0; j < (int)(records.size()); j++){
								r->next->RecordPtr.push_back((void*)(m));
								r = r->next;
							}
						}
						i++;
					}
					else
						error = true;
				}
				else if(tokens[i].type == tkValue){
					if(i+1 < (int)(tokens.size())){
						if(tokens[i+1].type != tkAs){
							int attributeIndex = -1;
							Table*fromTable = NULL;
							for(int k = 0; k < (int)(tables.size()); k++){
								for(int j = 0; j < (int)(tables[k]->AttributeName.size()); j++){
									if(tables[k]->AttributeName[j] == tokens[i].value){
										attributeIndex = j;
										view->AttributeName.push_back(tables[k]->AttributeName[j]);
										view->AttributeType.push_back(tables[k]->AttributeType[j]);
										fromTable=tables[k];
									}
								}
							}
							if(fromTable != NULL){
								Record* r = view->StartRec;
								for(int j = 0; j < (int)(records.size()); j++){
									if(attributeIndex < (int)(records[j]->RecordPtr.size())){
										//r->next->RecordPtr.push_back(records[j]->RecordPtr[attributeIndex]);
										deepCopyRecord(fromTable,r->next,records[j]->next,attributeIndex);
										r = r->next;
									}
									else
										error = true;
								}
							}
						}
					}
					else{
						int attributeIndex = -1;
						Table*fromTable = NULL;
						for(int k = 0; k < (int)(tables.size()); k++){
							for(int j = 0; j < (int)(tables[k]->AttributeName.size()); j++){
								if(tables[k]->AttributeName[j] == tokens[i].value){
									attributeIndex = j;
									view->AttributeName.push_back(tables[k]->AttributeName[j]);
									view->AttributeType.push_back(tables[k]->AttributeType[j]);
									fromTable=tables[k];
								}
							}
						}
						if(fromTable != NULL){
							Record* r = view->StartRec;
							for(int j = 0; j < (int)(records.size()); j++){
								if(attributeIndex < (int)(records[j]->RecordPtr.size())){
									//r->next->RecordPtr.push_back(records[j]->RecordPtr[attributeIndex]);
									deepCopyRecord(fromTable,r->next,records[j]->next,attributeIndex);
									r = r->next;
								}
								else
									error = true;
							}
						}
					}
				}
				else
					error = true;
			}
			if(error)
				cout<<"ERROR: Select Statement Incorrect."<<endl;
		}

		return view;
	}